package edu.washington.cs.workflow.analysis.guistructure.uievents;

import java.awt.Component;

import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import org.uispec4j.MenuItem;
import org.uispec4j.Panel;
import org.uispec4j.Trigger;
import org.uispec4j.UIComponent;

import edu.washington.cs.workflow.analysis.guistructure.Spec4JUtils;
import edu.washington.cs.workflow.analysis.guistructure.UIMenuPos;
import edu.washington.cs.workflow.analysis.guistructure.UIPos;
import edu.washington.cs.workflow.analysis.guistructure.uievents.UIEvent.WINDOW;
import edu.washington.cs.workflow.util.Utils;

public class MenuItemEvent extends AbstractUIEvent  {
	
	private final MenuItem item;
	private final UIAction action;
	
	public MenuItemEvent(MenuItem item, Panel panel, UIAction action) {
		Utils.checkNotNull(item);
		Utils.checkNotNull(action);
		Utils.checkNotNull(panel);
		Utils.checkTrue(action.equals(UIAction.Click), "illegal action: " + action);
		this.item = item;
		this.action = action;
		this.setCurrentPanel(panel);
	}
	
	@Override
	public void setUIComponentPos(UIPos pos) {
		Utils.checkTrue(pos.getClass().equals(UIMenuPos.class));
		super.setUIComponentPos(pos);
	}

	@Override
	public UIComponent getUIComponent() {
		return item;
	}

	@Override
	public UIAction getAction() {
		return action;
	}
	
	@Override
	protected WINDOW probeWindowInfoInternal() {
		Trigger t = this.getTrigger();
		WINDOW w = Spec4JUtils.getTriggeredDialog(this.item, t);
		Utils.checkNotNull(w);
		return w;
	}
	
	@Override
	public boolean canFireEvent() {
		Component c = this.item.getAwtComponent();
		if(c == null) {
			return false; //it can be a menu separator
		}
		Utils.checkTrue(c instanceof JMenuItem || c instanceof JPopupMenu,
				"illegal type: " + c.getClass());
		//check if it has sub-menu
		if(c instanceof JMenuItem) {
			if(((JMenuItem)c).getSubElements().length > 0) {
				return false;
			}
		}
		if(c instanceof JPopupMenu) {
			if(((JPopupMenu)c).getSubElements().length > 0) {
				return false;
			}
		}
		return this.item.isEnabled().isTrue();
	}

	protected Trigger getTrigger() {
		return this.item.triggerClick();
	}
	
	@Override
	protected UIEventOutcome fireEventInternal() {
		if(!this.canFireEvent()) {
			return null;
		}

		WINDOW winStatus = null;
		if(super.getWindowFlag() == null) {
			winStatus = super.probeWindowInfo();
		} else {
			winStatus = super.getWindowFlag();
		}
		Utils.checkNotNull(winStatus);
		
		UIEventOutcome outcome = new UIEventOutcome();
		Throwable error = null;

		if (!winStatus.equals(WINDOW.NONE)) {
			outcome.setWindowStatus(winStatus);
			outcome.setTrigger(this.getTrigger());
			return outcome;
		}

		try {
			this.item.click();
		} catch (Throwable e) {
			error = e;
		}

		if (error != null) {
			outcome.setError(error);
		}
		outcome.setWindowStatus(winStatus);
		// is the current panel not visible?
		outcome.currentPanelClosed(super.isCurrentPanelClosed());

		return outcome;
	}

	public String getMenuLabel() {
		if(this.item.getAwtComponent() instanceof JMenuItem) {
			return ((JMenuItem)this.item.getAwtComponent()).getText();
		} else if(this.item.getAwtComponent() instanceof JPopupMenu) {
			return ((JPopupMenu)this.item.getAwtComponent()).getLabel();
		} else {
			return "Unknown type: " + this.item.getAwtComponent().getClass();
		}
	}
	
	@Override
	public String toString() {
		return action + " menu item: " + this.item.getName() + ", " + this.getMenuLabel()
		  + ", path: " + this.getUIComponentPos();
	}

}
